\subsection{Пример генератора случайных чисел}
\label{FPU_PRNG}

Если нам нужны случайные значения с плавающей запятой в интервале от 0 до 1, самое простое это взять
\ac{PRNG} вроде Mersenne twister.
Он выдает случайные беззнаковые 32-битные числа (иными словами, он выдает 32 случайных бита).
Затем мы можем преобразовать это число в \Tfloat и затем разделить на \\
\GTT{RAND\_MAX} (\GTT{0xFFFFFFFF} в данном случае) --- полученное число будет в интервале от 0 до 1.

Но как известно, операция деления --- это медленная операция. 
Да и вообще хочется избежать лишних операций с FPU.
Сможем ли мы избежать деления?

\myindex{IEEE 754}
Вспомним состав числа с плавающей запятой: это бит знака, биты мантиссы и биты экспоненты. 
Для получения случайного числа, нам нужно просто заполнить случайными битами все биты мантиссы!

Экспонента не может быть нулевой (иначе число с плавающей точкой будет денормализованным), 
так что в эти биты мы запишем 0b01111111 --- это будет означать что экспонента равна единице.
Далее заполняем мантиссу случайными битами, знак оставляем в виде 0 (что значит наше число положительное), и вуаля.
Генерируемые числа будут в интервале от 1 до 2, так что нам еще нужно будет отнять единицу.

\newcommand{\URLXOR}{\url{http://go.yurichev.com/17308}}

В моем примере\footnote{идея взята здесь: \URLXOR} 
применяется очень простой линейный конгруэнтный генератор случайных чисел, выдающий 32-битные числа.
Генератор инициализируется текущим временем в стиле UNIX.

Далее, тип \Tfloat представляется в виде \IT{union} --- это конструкция \CCpp позволяющая 
интерпретировать часть памяти по-разному. В нашем случае, мы можем создать переменную типа \IT{union} 
и затем обращаться к ней как к \Tfloat или как к \IT{uint32\_t}. Можно сказать, что это хак, причем грязный.

% WTF?

Код целочисленного \ac{PRNG} точно такой же, как мы уже рассматривали ранее: \myref{LCG_simple}.
Так что и в скомпилированном виде этот код будет опущен.

\lstinputlisting[style=customc]{patterns/17_unions/FPU_PRNG/FPU_PRNG_RU.cpp}

\subsubsection{x86}

\lstinputlisting[caption=\Optimizing MSVC 2010,style=customasmx86]{patterns/17_unions/FPU_PRNG/MSVC2010_Ox_Ob0_RU.asm}

Имена функций такие странные, потому что этот пример был скомпилирован как Си++, и это манглинг имен в Си++, мы будем рассматривать это позже: \myref{namemangling}.

Если скомпилировать это в MSVC 2012, компилятор будет использовать SIMD-инструкции для FPU, читайте об этом здесь:

\myref{FPU_PRNG_SIMD}.

\subsubsection{MIPS}

\lstinputlisting[caption=\Optimizing GCC 4.4.5,style=customasmMIPS]{patterns/17_unions/FPU_PRNG/MIPS_O3_IDA_RU.lst}

Здесь снова зачем-то добавлена инструкция \INS{LUI}, которая ничего не делает.
Мы уже рассматривали этот артефакт ранее: \myref{MIPS_FPU_LUI}.

\subsubsection{ARM (\ARMMode)}

\lstinputlisting[caption=\Optimizing GCC 4.6.3 (IDA),style=customasmARM]{patterns/17_unions/FPU_PRNG/raspberry_GCC_O3_IDA_RU.lst}

\myindex{objdump}
\myindex{binutils}
\myindex{IDA}
Мы также сделаем дамп в objdump и увидим, что FPU-инструкции имеют немного другие имена чем в \IDA.
Наверное, разработчики IDA и binutils пользовались разной документацией?
Должно быть, будет полезно знать оба варианта названий инструкций.

\lstinputlisting[caption=\Optimizing GCC 4.6.3 (objdump),style=customasmARM]{patterns/17_unions/FPU_PRNG/raspberry_GCC_O3_objdump.lst}

Инструкции по адресам 0x5c в \TT{float\_rand()} и 0x38 в main() это (псевдо-)случайный мусор.

